import asyncio
import time


async def say_after(delay, what):
    await asyncio.sleep(delay)
    print(what)
    print(f"print {what} at {time.strftime('%X')}")
    return what


async def f1():
    print(f"started at {time.strftime('%X')}")

    await say_after(1, 'hello')
    await say_after(2, 'world')

    print(f"finished at {time.strftime('%X')}")


async def f2():
    '''task'''
    task1 = asyncio.create_task(say_after(1, 'hello'))
    task2 = asyncio.create_task(say_after(2, 'asyncio'))
    await task1
    await task2


async def f3():
    await asyncio.gather(say_after(1, 'hello'), say_after(2, 'asyncio'))
    # 如果 gather() 被取消，则序列中所有未提交的可等待对象都会被取消
    # 若aws中的Task或Future对象被取消，当作引发CancelledError，gather()不会取消


async def f4():
    ''' awaitable asyncio.shield(aw, *, loop=None)
        保护一个 可等待对象，防止其被取消。'''
    await asyncio.shield(say_after(1, "shield"))


async def sleep_5():
    await asyncio.sleep(3)
    print('sleep for 4 second')


async def f5():
    ''' coroutine asyncio.wait_for(aw, timeout, *, loop=None)
        指定timeout后超时，超时将引发asyncio.TimeoutError.
        函数将等待知道目标函数被取消。所以总时间可能超过timeout'''
    try:
        await asyncio.wait_for(sleep_5(), timeout=2)
    except asyncio.TimeoutError:
        print('timeout')
        await asyncio.sleep(2)


async def f54():
    '''加入sheild后sleep_5在超时后依旧运行'''
    try:
        res = asyncio.shield(sleep_5())
        await asyncio.wait_for(res, timeout=2)
    except asyncio.TimeoutError:
        print('timeout')
        await asyncio.sleep(2)


async def f6():
    task = asyncio.create_task(say_after(1, '1'))
    done, pending = await asyncio.wait({task}, timeout=2.1)
    if task in done:
        print('task in done')


async def f7():
    task = asyncio.create_task(say_after(1, '1'))
    for i in asyncio.as_completed({task}):
        a = await i
        print(a)

def f8():
    coro = asyncio.sleep(1, result=3)
    # Submit the coroutine to a given loop
    future = asyncio.run_coroutine_threadsafe(coro, loop)

    # Wait for the result with an optional timeout argument
    print(future.result(2))
    loop.stop()
    #如果在协程内产生了异常，将会通知返回的 Future 对象。它也可被用来取消事件循环中的任务:
    # try:
    #     result = future.result()
    # except asyncio.TimeoutError:
    #     print('The coroutine took too long, cancelling the task...')
    #     future.cancel()
    # except Exception as exc:
    #     print(f'The coroutine raised an exception: {exc!r}')
    # else:
    #     print(f'The coroutine returned: {result!r}')

print(f"now at {time.strftime('%X')}")
# asyncio.run(f8())
f8()
